package com.example.juc.controller;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author jl
 * @since 2021/9/25 18:32
 */
public class CompletableFutureNetMallDemo {
    static List<NetMall> list = Arrays.asList(new NetMall("jd"),
            new NetMall("pdd"),
            new NetMall("taobao"));

    static ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 20, 1, TimeUnit.MINUTES,
            new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());

    public static void main(String[] args) {
        long startTime1 = System.currentTimeMillis();
        List<String> list1 = getPriceByStep(list, "mysql");
        for (String s : list1) {
            System.out.println(s);
        }
        long endTime1 = System.currentTimeMillis();
        System.out.println("=== costTime: " + (endTime1 - startTime1) + "毫秒");

        long startTime2 = System.currentTimeMillis();
        List<String> list2 = getPriceByAsync(list, "mysql");
        for (String s : list2) {
            System.out.println(s);
        }
        long endTime2 = System.currentTimeMillis();
        System.out.println("=== costTime: " + (endTime2 - startTime2) + "毫秒");

    }

    // 同步 step by step
    public static List<String> getPriceByStep(List<NetMall> list, String productName) {
        return list.stream().map(e -> String.format(productName + " in %s price is %.2f", e.getMallName(), e.calcPrice(productName))).collect(Collectors.toList());
    }

    // 异步 多线程
    public static List<String> getPriceByAsync(List<NetMall> list, String productName) {
        return list.stream()
                .map(e -> CompletableFuture.supplyAsync(() ->
                        String.format(productName + " in %s price is %.2f", e.getMallName(), e.calcPrice(productName)), executor))
                .collect(Collectors.toList())
                .stream()
                .map(CompletableFuture::join).collect(Collectors.toList());
    }
}


class NetMall {

    private String mallName;

    public String getMallName() {
        return mallName;
    }

    public NetMall(String mallName) {
        this.mallName = mallName;
    }

    public double calcPrice(String productName) {
        // 模拟检索需要1秒钟
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }
}